Routing Configuration
The routing service is configured using a set of rules in the service’s configuration file or via the RoutingConfiguration object applied to RoutingExtension in the service host.
Routing rules consist
of message filters and routing targets. The routing service applies
these filters to incoming messages and if a message matches the filter
criteria, it is routed to appropriate target service(s).
Let’s take a look at the basic steps required to configure a routing service and its filters:
Step 1: Define Endpoints
One or more endpoints need to be defined for the routing service. The following example shows one such endpoint:
Example 3.
<services> <service behaviorConfiguration="RouterBehavior" name="System.ServiceModel.Routing.RoutingService"> <endpoint address="http://router.example.org/router" binding="basicHttpBinding" name="RequestResponse" contract="System.ServiceModel.Routing. IRequestReplyRouter" />
... add additional endpoints as necessary ...
</service> </services>
|
Step 2: Configure Service Behavior
The routing service’s behavior needs to be defined with the routing element in order to link the service to the routing rules in filterTableName, as follows:
Example 4.
<serviceBehaviors> <behavior name="RouterBehavior"> <routing filterTableName="routingRules" routeOnHeadersOnly="false" /> </behavior> </serviceBehaviors>
|
Step 3: Enumerate Target Endpoints
Potential routing
destinations (the target service endpoints) need to be defined. Note
that while the contracts of the destination service endpoints must
match, the bindings and binding configurations do not have to be
identical. This allows for any required runtime policy adjustments and
protocol transformation.
The following example shows two identified target service endpoints defined within the client element construct:
Example 5.
<client> <endpoint address="http://server1.example.org/Customers.svc" binding="basicHttpBinding" contract="*" name="CustomerService1" /> <endpoint address="http://server2.example.org/Customers.svc" binding="basicHttpBinding" contract="*" name="CustomerService2" /> </client>
|
Step 4: Define Message Filters
Next, message filter criteria need to be defined for routing services in the service host. In this example, the prefix attribute of the add
element defines the prefix for the custom XML namespace referenced in
XPath expressions, which are used to express the filter criteria:
Example 6.
<routing> <namespaceTable> <add prefix="my" namespace= "http://services.example.org/names"/> </namespaceTable> <filters> <filter name="CategoryFilter1" filterType="XPath" filterData="/s12:Envelope/s12:Header/ my:MsgCategory = 1" /> <filter name="CategoryFilter2" filterType="XPath" filterData="/s12:Envelope/s12:Header/ my:MsgCategory = 2" /> </filters> </routing>
|
Table 2 lists the filter types available in .NET 4.0, each of which can be used to define different matching behavior.
Table 2. Filter types to define different matching behaviors.
Filter Type | Matching Criteria |
---|
Action | matches a specific SOAP action |
XPath | evaluates an XPath expression against the entire message (header and body) |
EndpointAddress | matches the endpoint address (hostname matching is optional) |
EndpointAddressPrefix | matches the endpoint address against a specified prefix (hostname matching is optional) |
EndpointName | matches against the name of the endpoint receiving the message |
MatchAll | matches all incoming messages |
Custom | defines custom filter types based on the MessageFilter class |
And | combines two filters into one new filter |
Step 5: Create a Filter Table
Group the filters applied by a service instance using the filterTable element, as shown here:
Example 7.
<routing> <filters> ... </filters> <filterTables> <filterTable name="routingRules"> <add filterName=" CategoryFilter1" endpointName="CustomerService1"/> <add filterName=" CategoryFilter2" endpointName="CustomerService2"/> </filterTable> </filterTables> </routing>
|
The
routing service is now able to match any incoming message against these
filters and can then forward each message to target service endpoints
with matching criteria.
Note
The routing service can change its filter configuration without restarting the service when you pass a new set of RoutingConfiguration parameters to RoutingExtension in the service host. A new configuration cannot be applied by changing the configuration file.
Fault Tolerance
Service consumers often
need to implement logic to deal with fluctuating service availability.
This can be undesirable because it can lead to uncontrolled duplication,
but more importantly, inconsistent handling of various error types. The
involvement of intermediary logic within the routing service provides
an opportunity to handle service availability problems transparently to
service consumers. For example, the routing service can determine
whether to route messages to alternate destinations when a preferred
destination service endpoint is not available or too slow to respond.
Alternate destination endpoints can be identified as backup lists in the configuration file or programmatically, as follows:
Example 8.
<routing> <backupLists> <backupList name="CustomerServiceBackups"> <add endpointName="CustomerService2" /> <add endpointName="CustomerService3" /> </backupList> </backupLists> </routing>
|
The next example shows a filter rule that references the backup list defined in Example 7:
Example 9.
<routing> <filterTables> <filterTable name="filterTable1"> <add filterName="CategoryFilter1" endpointName="CustomerService1" backupList="CustomerServiceBackups"/> </filterTable> </filterTables> </routing>
|
The
routing service transmits messages to a backup location when it
receives a SOAP Fault with a timeout exception or an exception derived
from CommunicationException. The
service sequences through the backup list until it receives a response
message or a SOAP fault that does not indicate timeout or communication
problems.